#include <string>
#include <vector>
#include "Overlay.h"
//#include "SpriteCache.h"
#include "SurfaceCache.h"
#include "Level.h"
#include "LevelMap.h"
#include "Physics.h"
#define PHYSICS (Physics::GetSingleton())

Overlay::Overlay() : BaseUnit()
{
    m_identifier = "Unknown";
    m_statefulSprite = new StatefulSprite();
    setSpriteState("Unavailable");
//    m_collisionRegion = NULL;
    m_isGeneric = false;
}

Overlay::Overlay(const Vector2di p, const Vector2di s, uint transparentColour) : BaseUnit(p,s)
{
    m_identifier = "Unknown";
    m_statefulSprite = new StatefulSprite();
    setSpriteState("Unavailable");
    m_size = s;
    m_position = p;
//    m_collisionRegion = NULL;
    m_isGeneric = false;
    m_transparentColour = transparentColour;
}

Overlay::Overlay(string identifier, string imagefile, const Vector2di p, const Vector2di s, uint transparentColour) : BaseUnit(p,s)
{
    m_statefulSprite = new StatefulSprite();
    m_size = s;
    m_position = p;
//    m_collisionRegion = NULL;
    m_isGeneric = false;
    m_identifier = identifier;
    bool fromCache;
    m_surface = SurfaceCache::GetSurfaceCache()->GetSurface(imagefile.c_str(), fromCache);
    if (!m_surface)
    {
        cout << "Critical error: reading " << imagefile << " failed!" << endl;
        exit(-1);
    }
    m_transparentColour = transparentColour;
    setSpriteState("Unavailable");
};

Overlay::Overlay(string identifier, string imagefile, string target, const Vector2di p, const Vector2di s, uint transparentColour) : BaseUnit(p,s)
{
    m_statefulSprite = new StatefulSprite();
    m_size = s;
    m_position = p;
//    m_collisionRegion = NULL;
    m_isGeneric = false;
    m_identifier = identifier;
    bool fromCache;
    m_surface = SurfaceCache::GetSurfaceCache()->GetSurface(imagefile.c_str(), fromCache);
    if (!m_surface)
    {
        cout << "Critical error: reading " << imagefile << " failed!" << endl;
        exit(-1);
    }
    m_transparentColour = transparentColour;
    m_target = target;
    int sheetWidth = m_surface->w/m_size.x;
    int sheetHeight = m_surface->h/m_size.y;

    addSpriteState("Unavailable", sheetWidth, sheetHeight, 0, sheetWidth, 10, m_transparentColour);
    if (sheetHeight > 1) addSpriteState("Available", sheetWidth, sheetHeight, sheetWidth*1, sheetWidth, 10, m_transparentColour);
    if (sheetHeight > 2) addSpriteState("Focused", sheetWidth, sheetHeight, sheetWidth*2, sheetWidth, 10, m_transparentColour);
    if (sheetHeight > 3) addSpriteState("Completed", sheetWidth, sheetHeight, sheetWidth*3, sheetWidth, 10, m_transparentColour);
    if (sheetHeight > 4) addSpriteState("Enabling", sheetWidth, sheetHeight, sheetWidth*4, sheetWidth, 10, m_transparentColour);
    if (sheetHeight > 5) addSpriteState("Focusing", sheetWidth, sheetHeight, sheetWidth*5, sheetWidth, 10, m_transparentColour);
    if (sheetHeight > 6) addSpriteState("Completing", sheetWidth, sheetHeight, sheetWidth*6, sheetWidth, 10, m_transparentColour);
    uint i;
    string statename;
    for (i = 8; i < sheetHeight; ++i) {
        statename = "ExtraState" + i;
        addSpriteState(statename, sheetWidth, sheetHeight, sheetWidth*(i-1), sheetWidth, 10, m_transparentColour);
    }
    setSpriteState("Unavailable");
};

Overlay::Overlay(StatefulSprite *sprite) : BaseUnit()
{
    m_identifier = "Unknown";
    m_statefulSprite = sprite;
    m_isGeneric = false;
}

Overlay::~Overlay()
{
    m_sprite = NULL;
//    m_collisionRegion = NULL;
    m_statefulSprite = NULL;
    m_isGeneric = false;
    //dtor
}

int Overlay::getWidth() const
{
    if (m_sprite)
    {
        return m_sprite->getWidth();
    }
    else
    {
        return m_size.x;
    }
}

int Overlay::getHeight() const
{
    if (m_sprite)
    {
        return m_sprite->getHeight();
    }
    else
    {
        return m_size.y;
    }
}

Vector2df Overlay::getSize() const
{
    if (m_sprite)
    {
        return Vector2df(m_sprite->getWidth(),m_sprite->getHeight());
    }
    else
    {
        return m_size;//Vector2df(-1,-1);
    }
}

void Overlay::addSpriteState(string state, uint sheetWidth, uint sheetHeight, uint startIndex, uint numFrames, uint frameRate, uint transparentColour)
{
    if (m_statefulSprite) {
        m_statefulSprite->addSpriteState(state, m_surface, sheetWidth, sheetHeight, startIndex, numFrames, frameRate, transparentColour);
    }
}

// Set the current state
void Overlay::setSpriteState(string stateName)
{
    m_statefulSprite->setSpriteState(stateName);
    m_sprite = m_statefulSprite->getSpriteForState(stateName);
    //m_collisionRegion = m_statefulSprite->getCollisionForState(stateName);
}

void Overlay::update()
{
    m_counter.update();
    if (m_sprite) m_sprite->update();
    if (m_parent)
    {
        if (m_parent->getDirection() == 1)
            setPosition(Vector2df(m_parent->getPosition().x + 12,m_parent->getPosition().y - getHeight() - 2));
        else
            setPosition(Vector2df(m_parent->getPosition().x  - 18,m_parent->getPosition().y - getHeight() - 2));
    }
    if (m_sprite)
    {
        m_statefulSprite->playFrameSound(m_sprite->getCurrentFrame());
    }
    //if (getCollision())
    //    PHYSICS->calculatePhysics(this);
};

void Overlay::checkCollision()
{
//    if (getCollision() && not hasCollisionFlag(CollisionFlags::NO_UNITS))
//        PHYSICS->checkUnitCollision(this,getLevel()->GetFriendlies());
//
//    if (getCollision())
//        PHYSICS->checkMapCollision(this);
}

int Overlay::getState() const
{
    return 0;
}

void Overlay::hit(const SimpleDirection dir, BaseUnit* const player, CRstring parameter)
{
    handleEvent("Hit");
}

void Overlay::hitMap(MapData* const data, const CollisionObject* const obj)
{
    Vector2df correction = obj->getTotalCorrection();
    incY(m_velocity.y + correction.y);
    if (abs(correction.y) > 0)
    {
        m_velocity.y = 0;
        m_acceleration[0].y = 0;
        m_acceleration[1].y = 0;
    }
    if (abs(correction.x) + abs(correction.y) > 0)
    {
        // If pushed against a wall, flip it over
        if (correction.x != 0)
        {
            // Change movement direction
            m_velocity.x *= -1;
            m_acceleration[0].x *= -1;
            m_acceleration[1].x *= -1;
        }
    }
    incX(m_velocity.x + correction.x);
}

void Overlay::handleEvent(string eventName)
{
    if (m_statefulSprite)
    {
        vector< vector<string> > events = m_statefulSprite->getEvents(eventName);
        vector< vector<string> >::iterator it;
        vector<string> cur;

        for (it=events.begin(); it!=events.end(); ++it)
        {
            cur = (*it);
            if (cur.size() > 1)
            {
                if (cur[0] == "Hero")
                {
                    if (cur[1] == "AddCoins")
                    {
                        Hero *hero = (Hero *)((Level *)m_level)->GetHero();
                        if (cur.size()>2)
                        {
                            hero->addCoins(atoi(cur[2].c_str()));
                        }
                        else
                        {
                            hero->addCoins(1);
                        }
                    }
                }
                else if (cur[0] == "Level")
                {
                }
                else if (cur[0] == "Self")
                {
                    if (cur[1] == "Remove")
                    {
                        m_shouldBeRemoved = true;
                    }
                    else if (cur[1] == "Sound" && cur.size()>2)
                    {
                        playSound(cur[2]);
                    }
                    else if (cur[1] == "State" && cur.size()>2)
                    {
                        setSpriteState(cur[2]);
                    }
                }
            }
        }
    }
}

void Overlay::render()
{
    BaseUnit::render();
//#ifdef _DEBUG
//    if (m_collisionRegion)
//    {
//        m_collisionRegion->setPosition(getScreenPosition());
//        m_collisionRegion->render();
//        m_collisionRegion->setPosition(Vector2df(0,0));
//    }
//#endif
};
